#include "unity.h"
#include "command_proc.h"

// Include any other necessary headers
#include <string.h>


void setUp(void)
{
    // This is run before each test
}

void tearDown(void)
{
    // This is run after each test
}

void test_FlashEraseCommandInUpdateMode_Should_ReturnDataInjectionHandle(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_FLASH_ERASE;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_UPDATE;
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(CMDHANDLE_DATAINJ, result);
    TEST_ASSERT_EQUAL(0, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(DATAINJ_FLASH_ERASE, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_FlashEraseCommandNotInUpdateMode_Should_ReturnDoneWithError(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_FLASH_ERASE;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE; // Not in update mode
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_TIMING_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(DATAINJ_FLASH_ERASE, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_DataInjectionCommandNotInIdleMode_Should_ReturnDoneWithError(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_SAMPLE_PERIOD;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_UPDATE; // Not in idle mode
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_TIMING_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(DATAINJ_SAMPLE_PERIOD, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_SamplePeriodCommandInIdleMode_Should_ReturnDataInjectionHandle(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_SAMPLE_PERIOD;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(CMDHANDLE_DATAINJ, result);
    TEST_ASSERT_EQUAL(0, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(DATAINJ_SAMPLE_PERIOD, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_CloudThresholdCommandInIdleMode_Should_ReturnDataInjectionHandle(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_CLOUD_THREHOLD;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(CMDHANDLE_DATAINJ, result);
    TEST_ASSERT_EQUAL(0, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(DATAINJ_CLOUD_THREHOLD, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_IPConfigCommandInIdleMode_Should_ReturnDataInjectionHandle(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_IP_CFG;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(CMDHANDLE_DATAINJ, result);
    TEST_ASSERT_EQUAL(0, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(DATAINJ_IP_CFG, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_CalibrationParamCommandInIdleMode_Should_ReturnDataInjectionHandle(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_CALIBRATION_PARA;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(CMDHANDLE_DATAINJ, result);
    TEST_ASSERT_EQUAL(0, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(DATAINJ_CALIBRATION_PARA, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_UndefinedCommandInIdleMode_Should_ReturnDoneWithError(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = 0xFF; // Undefined command
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_UNDEFINE_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(0xFF, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_CommControlFlagIsAlwaysSetToFuncID(void)
{
    // Arrange
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    u32 testFuncID = 0x5A;
    busService.TC_CmdData.funcID = testFuncID;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    // Act
    u32 result = _BusInjectData_proc(&busService);
    
    // Assert
    TEST_ASSERT_EQUAL(testFuncID, busService.Telemeter_TX_Data.Comm_Control_Flag);
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_UNDEFINE_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
}



void test_FirstValidDataInjectionCommand(void)
{
    // Test the first valid data injection command
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_SAMPLE_PERIOD; // First valid command
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    u32 result = _BusInjectData_proc(&busService);
    
    TEST_ASSERT_EQUAL(CMDHANDLE_DATAINJ, result);
    TEST_ASSERT_EQUAL(0, busService.Telemeter_TX_Data.Comm_Error_Flag);
}

void test_LastValidDataInjectionCommand(void)
{
    // Test the last valid data injection command
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_CALIBRATION_PARA; // Last valid command
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    u32 result = _BusInjectData_proc(&busService);
    
    TEST_ASSERT_EQUAL(CMDHANDLE_DATAINJ, result);
    TEST_ASSERT_EQUAL(0, busService.Telemeter_TX_Data.Comm_Error_Flag);
}

void test_CommandJustBeforeValidRange(void)
{
    // Test command just before valid range
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_SAMPLE_PERIOD - 1; // Just before valid range
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    u32 result = _BusInjectData_proc(&busService);
    
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_UNDEFINE_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
}

void test_CommandJustAfterValidRange(void)
{
    // Test command just after valid range
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_CALIBRATION_PARA + 1; // Just after valid range
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    u32 result = _BusInjectData_proc(&busService);
    
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_UNDEFINE_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
}



void test_FlashEraseInTestMode(void)
{
    // Test flash erase command in test mode (should fail)
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_FLASH_ERASE;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_TEST; // Test mode, not update mode
    
    u32 result = _BusInjectData_proc(&busService);
    
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_TIMING_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
}

void test_DataInjectionInWorkMode(void)
{
    // Test data injection in work mode (should fail)
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = DATAINJ_SAMPLE_PERIOD;
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_WORK; // Work mode, not idle
    
    u32 result = _BusInjectData_proc(&busService);
    
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_TIMING_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
}

void test_ZeroFuncIDInIdleMode(void)
{
    // Test zero funcID in idle mode
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = 0; // Zero funcID
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    u32 result = _BusInjectData_proc(&busService);
    
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_UNDEFINE_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(0, busService.Telemeter_TX_Data.Comm_Control_Flag);
}

void test_MaxFuncIDInIdleMode(void)
{
    // Test maximum funcID in idle mode
    B1553_BusService busService;
    memset(&busService, 0, sizeof(B1553_BusService));
    
    busService.TC_CmdData.funcID = 0xFF; // Max funcID
    busService.Telemeter_TX_Data.Work_Mode_Flag = SYS_MODE_IDLE;
    
    u32 result = _BusInjectData_proc(&busService);
    
    TEST_ASSERT_EQUAL(CMDHANDLE_DONE, result);
    TEST_ASSERT_EQUAL(TELEMETRY_BUSCMD_UNDEFINE_ERR, busService.Telemeter_TX_Data.Comm_Error_Flag);
    TEST_ASSERT_EQUAL(0xFF, busService.Telemeter_TX_Data.Comm_Control_Flag);
}